package com.smartcampusbackend.aspect;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.smartcampusbackend.annotation.DataLog;
import com.smartcampusbackend.model.User;
import com.smartcampusbackend.service.SystemLogService;
import com.smartcampusbackend.service.TokenService;
import com.smartcampusbackend.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class DataLogAspect {
    
    @Autowired
    private SystemLogService systemLogService;
    
    @Autowired
    private TokenService tokenService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Around("@annotation(dataLog)")
    public Object around(ProceedingJoinPoint joinPoint, DataLog dataLog) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        Exception exception = null;
        
        try {
            // 执行原方法
            result = joinPoint.proceed();
            return result;
        } catch (Exception e) {
            exception = e;
            throw e;
        } finally {
            // 记录日志
            try {
                recordDataLog(joinPoint, dataLog, startTime, result, exception);
            } catch (Exception e) {
                log.error("记录数据操作日志失败", e);
            }
        }
    }
    
    private void recordDataLog(ProceedingJoinPoint joinPoint, DataLog dataLog, long startTime, Object result, Exception exception) {
        try {
            // 获取请求信息
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                return;
            }
            
            HttpServletRequest request = attributes.getRequest();
            String ipAddress = getClientIpAddress(request);
            String userAgent = request.getHeader("User-Agent");
            String requestUrl = request.getRequestURL().toString();
            String requestMethod = request.getMethod();
            
            // 获取当前用户
            User currentUser = getCurrentUser(request);
            if (currentUser == null) {
                return;
            }
            
            // 计算执行时间
            long executionTime = System.currentTimeMillis() - startTime;
            
            // 获取方法信息
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            
            // 构建操作描述
            String action = dataLog.action();
            if (action.isEmpty()) {
                action = method.getName();
            }
            
            String description = dataLog.description();
            if (description.isEmpty()) {
                description = "执行" + method.getName() + "方法";
            }
            
            // 获取请求参数
            String requestParams = "";
            if (dataLog.logParams()) {
                try {
                    requestParams = objectMapper.writeValueAsString(joinPoint.getArgs());
                    if (requestParams.length() > 500) {
                        requestParams = requestParams.substring(0, 500) + "...";
                    }
                } catch (Exception e) {
                    log.warn("序列化请求参数失败", e);
                }
            }
            
            // 获取响应结果
            String responseResult = "";
            if (dataLog.logResult() && result != null) {
                try {
                    responseResult = objectMapper.writeValueAsString(result);
                    if (responseResult.length() > 500) {
                        responseResult = responseResult.substring(0, 500) + "...";
                    }
                } catch (Exception e) {
                    log.warn("序列化响应结果失败", e);
                }
            }
            
            // 记录日志
            if (exception != null) {
                systemLogService.logError(
                    currentUser.getUsername(),
                    currentUser.getId(),
                    action,
                    description + " - 异常: " + exception.getMessage(),
                    ipAddress,
                    userAgent,
                    requestUrl,
                    requestMethod,
                    requestParams,
                    500,
                    exception.getMessage(),
                    executionTime
                );
            } else {
                systemLogService.logData(
                    currentUser.getUsername(),
                    currentUser.getId(),
                    action,
                    description,
                    ipAddress,
                    userAgent,
                    requestUrl,
                    requestMethod,
                    requestParams,
                    200,
                    executionTime,
                    "SUCCESS"
                );
            }
        } catch (Exception e) {
            log.error("记录数据操作日志失败", e);
        }
    }
    
    /**
     * 获取客户端真实IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }
        
        return request.getRemoteAddr();
    }
    
    /**
     * 获取当前登录用户信息
     */
    private User getCurrentUser(HttpServletRequest request) {
        try {
            String token = request.getHeader("Authorization");
            if (token != null && token.startsWith("Bearer ")) {
                token = token.substring(7);
                String username = tokenService.getUsernameByToken(token);
                if (username != null) {
                    return userService.getByUsername(username);
                }
            }
        } catch (Exception e) {
            log.warn("获取当前用户信息失败", e);
        }
        return null;
    }
} 